﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace SplitAndEncrypt
{

    class Program
    {

        private const int RIJNDAEL_SECRET_KEY_SIZE_BITS = 256;
        private const int RIJNDAEL_INITIAL_VECTOR_SIZE_BITS = 128;
        static void Main(string[] args)
        {
            //string originalMessage = "aaa";
            //Console.WriteLine("Original message: {0}", originalMessage);
            //string password = "$3cR3t-P@$$w0rd";
            //string encryptedMessage = EncryptString(originalMessage, password);
            //Console.WriteLine("Encrypted message: {0}", encryptedMessage);
            //string decryptedMessage = DecryptString(encryptedMessage, password);
            //Console.WriteLine("Decrypted message: {0}", decryptedMessage);
            Devide();
            Collect();

        }

        public static void Devide()
        {
            using (FileStream inFile =
    new FileStream("Debi_Nova_-_Drummer_Boy_.mp3", FileMode.Open))
            {
                int currFile = 1;
                byte[] buf = new byte[15 * 4096];
                //byte[] encrBuf = EncryptBytes(buf, "milen");
                while (true)
                {
                    int bytesRead = inFile.Read(buf, 0, buf.Length);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    byte[] encrBuf = EncryptBytes(buf, "milen");
                    int bytesRead1 = inFile.Read(encrBuf, 0, encrBuf.Length);
                    
               
                    using (FileStream outFile = new FileStream(string.Format("{1}part{0:0000}", currFile,inFile.Name), FileMode.Create))
                    {
                        outFile.Write(encrBuf, 0, bytesRead1);
                    }
                    currFile++;
                }
            }
        }

        public static void Collect()
        {
            using (FileStream inFile =
    new FileStream(string.Format("1" + "Debi_Nova_-_Drummer_Boy_.mp3"), FileMode.Create))
            {
                int currFile = 1;
                byte[] buf = new byte[5 * 4096];
               
                while (true)
                {
                    try
                    {
                        using (FileStream outFile = new FileStream(string.Format("{1}part{0:0000}", currFile, "Debi_Nova_-_Drummer_Boy_.mp3"), FileMode.Open))
                        {
                            while (true)
                            {
                                int bytesRead = outFile.Read(buf, 0, buf.Length);
                                if (bytesRead == 0)
                                {
                                    break;
                                }
                                byte[] decrBuf = DecryptBytes(buf, "milen");
                                int bytesRead1 = outFile.Read(decrBuf, 0, decrBuf.Length);
                                if (bytesRead == 0)
                                {
                                    break;
                                }

                                inFile.Write(decrBuf, 0, bytesRead1);
                            }
                        }
                        currFile++;
                    }
                    catch (FileNotFoundException)
                    {
                        break;
                    }
                }
            }
        }


        private static ICryptoTransform CreateRijndaelEncryptor(string password)
        {
            byte[] salt = Encoding.ASCII.GetBytes(password.Length.ToString());
            PasswordDeriveBytes passwordDerivedBytes = new PasswordDeriveBytes(password, salt);
            byte[] secretKey = passwordDerivedBytes.GetBytes(RIJNDAEL_SECRET_KEY_SIZE_BITS / 8);
            byte[] initialVector = passwordDerivedBytes.GetBytes(RIJNDAEL_INITIAL_VECTOR_SIZE_BITS / 8);
            RijndaelManaged RijndaelCipher = new RijndaelManaged();
            RijndaelCipher.Padding = PaddingMode.ISO10126;
            ICryptoTransform encryptor = RijndaelCipher.CreateEncryptor(secretKey, initialVector);
            return encryptor;
        }

        private static byte[] EncryptBytes(byte[] bytesToEncrypt, string password)
        {
            ICryptoTransform encryptor = CreateRijndaelEncryptor(password);
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream =
                new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
            using (cryptoStream)
            {
                cryptoStream.Write(bytesToEncrypt, 0, bytesToEncrypt.Length);
                cryptoStream.FlushFinalBlock();
                byte[] encryptedBytes = memoryStream.ToArray();
                return encryptedBytes;
            }
        }

        private static string EncryptString(string stringToEncrypt, string password)
        {
            byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(stringToEncrypt);
            byte[] encryptedBytes = EncryptBytes(bytesToEncrypt, password);
            string encryptedString = Convert.ToBase64String(encryptedBytes);
            return encryptedString;
        }

        private static ICryptoTransform CreateRijndaelDecryptor(string password)
        {
            byte[] salt = Encoding.ASCII.GetBytes(password.Length.ToString());
            PasswordDeriveBytes passwordDerivedBytes = new PasswordDeriveBytes(password, salt);
            byte[] secretKey = passwordDerivedBytes.GetBytes(RIJNDAEL_SECRET_KEY_SIZE_BITS / 8);
            byte[] initialVector = passwordDerivedBytes.GetBytes(RIJNDAEL_INITIAL_VECTOR_SIZE_BITS / 8);
            RijndaelManaged RijndaelCipher = new RijndaelManaged();
            RijndaelCipher.Padding = PaddingMode.ISO10126;
            ICryptoTransform decryptor = RijndaelCipher.CreateDecryptor(secretKey, initialVector);
            return decryptor;
        }

        private static byte[] DecryptBytes(byte[] encryptedBytes, string password)
        {
            ICryptoTransform encryptor = CreateRijndaelDecryptor(password);
            MemoryStream encryptedBytesStream = new MemoryStream(encryptedBytes);
            MemoryStream decryptedBytesStream = new MemoryStream();
            CryptoStream cryptoStream =
                new CryptoStream(encryptedBytesStream, encryptor, CryptoStreamMode.Read);
            using (cryptoStream)
            {
                byte[] buffer = new byte[encryptedBytes.Length];
                while (true)
                {
                    int bytesRead = cryptoStream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    decryptedBytesStream.Write(buffer, 0, bytesRead);
                }
                byte[] decryptedBytes = decryptedBytesStream.ToArray();
                return decryptedBytes;
            }
        }

        private static string DecryptString(string encryptedString, string password)
        {
            byte[] encryptedBytes = Convert.FromBase64String(encryptedString);
            byte[] decryptedBytes = DecryptBytes(encryptedBytes, password);
            string decryptedString = Encoding.UTF8.GetString(decryptedBytes);
            return decryptedString;
        }
    }
}
